package com.cy.lib.net;

import android.os.AsyncTask;

import com.cy.lib.util.MapUtils;
import com.cy.lib.util.StreamUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by CY on 2015/8/5.
 */
public class HttpRequest extends AsyncTask<Object, Object, HttpRequest.ResultInfo> {

    protected OnHttpRequestListener mRequestListener;
    protected HashMap<String, Object> mParams;
    protected String mUrl;

    private int ReadTimeOut = 0;
    private int ConnectTimeOut = 0;
    private boolean isUserCache;

    private static ExecutorService mThreadPool;
    private Object Lock = new Object();

    private Object mTag;

    public HttpRequest(String url) {
        this(url, null);
    }

    public HttpRequest(String url, Object tag) {
        this(url, null, tag);
    }

    public HttpRequest(String url, HashMap<String, Object> map, Object tag) {
        this(url, map, null, tag);
    }

    public HttpRequest(String url, HashMap<String, Object> map, OnHttpRequestListener listener, Object tag) {
        mParams = map;
        mRequestListener = listener;
        mUrl = url;
        mTag = tag;
    }


    /**
     * 同步请求
     */
    public ResultInfo startSync() {
        return startRequest();
    }

    /**
     * 异步请求
     */
    public HttpRequest startASync() {

        synchronized (Lock) {
            if (mThreadPool == null) {
                mThreadPool = Executors.newCachedThreadPool();
            }
            executeOnExecutor(mThreadPool);
            return this;
        }
    }


    @Override
    protected ResultInfo doInBackground(Object... params) {

        return startRequest();
    }

    @Override
    protected void onPostExecute(ResultInfo result) {
        super.onPostExecute(result);
        onRequestResult(result);
    }

    @Override
    protected void onCancelled() {
        mRequestListener = null;
        super.onCancelled();
    }

    @Override
    protected void onCancelled(ResultInfo resultInfo) {
        mRequestListener = null;
        super.onCancelled(resultInfo);
    }

    /**
     * 请求开始
     *
     * @return
     */
    private ResultInfo startRequest() {
        try {
            return connect();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 请求结果
     *
     * @param result
     */
    protected void onRequestResult(ResultInfo result) {
        if (mRequestListener != null) {
            if (result != null && result.getResponseCode() == HttpURLConnection.HTTP_OK) {
                mRequestListener.onResult(ResultState.SUCCESS, result);
            } else {
                mRequestListener.onResult(ResultState.FAIL, result);
            }
        }
    }


    private ResultInfo connect() throws IOException {

        HttpURLConnection connection = (HttpURLConnection) new URL(mUrl).openConnection();
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setReadTimeout(ReadTimeOut);
        connection.setConnectTimeout(ConnectTimeOut);

        if (mParams != null && !mParams.isEmpty()) {
            connection.getOutputStream().write(outData());
            connection.getOutputStream().flush();
        }
        int responseCode = connection.getResponseCode();
        String str = null;
        if (responseCode == HttpURLConnection.HTTP_OK) {
            InputStream is = connection.getInputStream();
            str = StreamUtils.toStr(is);
            is.close();
        }
        ResultInfo info = new ResultInfo(connection.getDate(), connection.getResponseCode(), str, connection.getContentEncoding(), connection.getResponseMessage(), mTag);

        return info;
    }

    private byte[] outData() {
        String str = MapUtils.toUrlParams(mParams);
        return str != null ? str.getBytes() : null;
    }

    /* *参数设置 Start***********************************/

    public HttpRequest setReadTimeOut(int readTimeOut) {
        ReadTimeOut = readTimeOut;
        return this;
    }

    public HttpRequest setConnectTimeOut(int connectTimeOut) {
        ConnectTimeOut = connectTimeOut;
        return this;
    }

    public HttpRequest setUseCaches(boolean newValue) {
        isUserCache = newValue;
        return this;
    }
    /* *参数设置 End***********************************/

    public interface OnHttpRequestListener {
        void onResult(HttpRequest.ResultState state, ResultInfo result);
    }

    public enum ResultState {
        SUCCESS, FAIL
    }

    public static class ResultInfo {

        private long Date;
        private int ResponseCode;
        private String ResponseResult;
        private String ContentEncoding;
        private String ResponseMessage;

        private Object mTag;

        public ResultInfo() {
        }

        public ResultInfo(long date, int responseCode, String responseResult, String contentEncoding, String responseMessage, Object tag) {
            Date = date;
            ResponseCode = responseCode;
            ResponseResult = responseResult;
            ContentEncoding = contentEncoding;
            ResponseMessage = responseMessage;
            mTag = tag;
        }

        public long getDate() {
            return Date;
        }

        public int getResponseCode() {
            return ResponseCode;
        }

        public String getResponseResult() {
            return ResponseResult;
        }

        public String getContentEncoding() {
            return ContentEncoding;
        }

        public String getResponseMessage() {
            return ResponseMessage;
        }

        public ResultInfo setDate(long date) {
            Date = date;
            return this;
        }

        public ResultInfo setResponseCode(int responseCode) {
            ResponseCode = responseCode;
            return this;
        }

        public ResultInfo setResponseResult(String responseResult) {
            ResponseResult = responseResult;
            return this;
        }

        public ResultInfo setContentEncoding(String contentEncoding) {
            ContentEncoding = contentEncoding;
            return this;
        }

        public ResultInfo setResponseMessage(String responseMessage) {
            ResponseMessage = responseMessage;
            return this;
        }

        public Object getTag() {
            return mTag;
        }

        public ResultInfo setTag(Object tag) {
            this.mTag = tag;
            return this;
        }
    }
}
